<?php
/**
 * Created by PhpStorm.
 * User: My
 * Date: 2019/6/20
 * Time: 19:40
 */

namespace App\Http\Common\Util;

use App\Http\Common\Helper\LogHelper;

class Timer
{
    protected $name     = null;
    protected $ts_begin = null;
    protected $stage    = [];
    /** @var Timer */
    protected static $instance;

    /**
     * @param string $name
     * @return Timer
     */
    public static function getInstance($name = '')
    {
        if (!static::$instance) {
            static::$instance = new static();
        }

        if ($name) {
            static::$instance->changeName($name);
        }

        return static::$instance;
    }

    public function __construct($name = '')
    {
        $this->name = $name;
        $this->init();
    }

    #for yii component
    public function init()
    {
        $this->ts_begin = microtime(true);
        $this->stage = [];
    }

    public function changeName($name)
    {
        $this->name = $name;
    }

    public function log($extra = '')
    {
        $now = microtime(true);
        LogHelper::info("[timer.elapsed] $this->name: $now - $this->ts_begin $extra");
    }

    public function getElapsed()
    {
        return microtime(true) - $this->ts_begin;
    }

    public function record($stage = '', $recordTime = true)
    {
        $cur_ts = microtime(true);
        if ($this->stage) {
            $cnt = count($this->stage);
            if ($cur_ts - $this->stage[$cnt - 1][1] > 0.5) {
                LogHelper::warning($stage . '耗时超过 0.5s');
            }
        }

        if ($recordTime) {
            $this->stage[] = [$stage, $cur_ts];
        } else {
            $this->stage[] = [$stage, ''];
        }

    }

    public function logAll($echo = false)
    {
        $logInfo = [];
        $last_ts = $this->ts_begin;
        foreach ($this->stage as $stage_info) {
            list($stage, $ts) = $stage_info;
            if ($ts !== '') {
                $stage_elapsed = $ts - $last_ts;
                $last_ts = $ts;
                $logInfo[] = sprintf("[%s:%.6f]", $stage, $stage_elapsed);
            } else {
                $logInfo[] = sprintf("[%s]", $stage);
            }

        }
        $elapsed = $this->getElapsed();
        $logInfo = join(' ', $logInfo);

        $logBody = "[timer.elapsed] $this->name: $elapsed $logInfo";

        if ($echo) {
            echo $logBody;
        } else {
            LogHelper::info($logBody);
        }
    }

    public function logAllAndInit()
    {
        $this->logAll();
        $this->init();
    }
}